'''
Created on Apr 23, 2013

@author: alex
'''
import socket, select
class Handler:
    def __init__(self, connection, cacheActive, cache, timeout = 15):
        self.clientSocket = connection[0]
        self.cacheActive = cacheActive
        self.cache = cache
        self.timeout = timeout
        self.inBuffer = ''
        self.method, self.url, self.protocol = self.getHeader()
        #print 'method: '+str(self.method)+' url: '+str(self.url)+' protocol: '+str(self.protocol)
        if self.method != 'GET':
            print 'Non-GET method requested!'
        self.get()
        self.clientSocket.close()
        self.toHost.close()
    
    def getHeader(self):
        while 1:
            self.inBuffer += self.clientSocket.recv(8192)
            end = self.inBuffer.find('\n')
            if  end != -1:
                break
        returnvals = (self.inBuffer[:end+1]).split()
        self.inBuffer = self.inBuffer[end+1:]
        return returnvals
    
    def connectTo(self, host):
        i = host.find(':')
        if i != -1:
            port = int(host[i+1:])
            host = host[:i]
        else:
            port = 80
        (family, _, _, _, address) = socket.getaddrinfo(host, port)[0]
        self.toHost = socket.socket(family)
        self.toHost.connect(address)
        
    def get(self):
        #todo: conditional get
        self.url = self.url[7:]
        i= self.url.find('/')
        host = self.url[:i]
        path = self.url[i:]
        i1 = path.find('.')
        extension = ''
        if i1 != -1:
            extension = path[i1:]
        if self.cacheActive:
            #print 'doing stuff'
            inCache = self.cache.getFileFromCache('http://'+host+path)
            if inCache == False:
                self.cache.getFile('http://'+host+path)
                self.connectTo(host)
                getString = self.method+' '+path+' '+self.protocol+'\n'+self.inBuffer
                #print getString
                self.toHost.send(getString)
                self.inBuffer = ''
                self.io()
            else:
                self.cacheIO(inCache)
                self.cache.unlockFile('http://'+host+path)
        else:
            self.connectTo(host)
            getString = self.method+' '+path+' '+self.protocol+'\n'+self.inBuffer
            #print getString
            self.toHost.send(getString)
            self.inBuffer = ''
            self.io()
        
    def io(self):
        count = 0
        sockets = [self.clientSocket, self.toHost]
        while 1:
           # print 'while loop'
            count += 1
            (rec, _, error) = select.select(sockets, [], sockets, 3)
            if error:
                break
            if rec:
                for i in rec:
                    #print 'rec loop'
                    i1 = i.recv(8192)
                    if i is self.clientSocket:
                        #print 'sending to host'
                        out = self.toHost
                    else:
                       # print 'sending to client'
                        out = self.clientSocket
                        
                    if i1:
                        #print 'sending'
                        #print i1
                        out.send(i1)
                        count = 0
            if count == self.timeout/3:
                #print 'I\'m finished!!!'
                break
                        
    def cacheIO(self, toSend):
        out = self.clientSocket
        count = 0
        sockets = [self.clientSocket, self.toHost]
        httpCode = 'HTTP/1.1 200 OK\n'
        toSend = httpCode + toSend
        out.send(toSend)
        while 1:
            #print 'while loop'
            count += 1
            (rec, _, error) = select.select(sockets, [], sockets, 3)
            if error:
                break
            if rec:
                for i in rec:
                    #print 'rec loop'
                    i1 = i.recv(8192)
                    if i is self.clientSocket:
                        #print 'sending to host'
                        out = self.toHost
                    else:
                        #print 'sending to client'
                        out = self.clientSocket
                        
                    if i1:
                        #print 'sending'
                        #print i1
                        out.send(i1)
                        count = 0
            if count == self.timeout/3:
                #print 'I\'m finished!!!'
                break
        
        